#include <stdio.h>

#include "mod_relay_mod.h"
#include <string.h>
#include <stdlib.h>

/*=======================函数声明===============================*/


/** IO function ： */
static int find_node(circuit_node_t *node_ptr, void *argPtr);



/*=======================end===============================*/


/**
 * @brief 复位
 * @param node_ptr 端点指针
*/
static void OP_FUNC_RESET(TYPE_MOD_RELAY)(void *node_ptr)
{
    // 初始化 设备的 实时运行参数

   
}

/**
 * @brief 初始化数据
*/
static uint32_t OP_FUNC_INIT(TYPE_MOD_RELAY)(void *node_ptr, void *config_data_ptr)
{
    uint32_t res = 0; // (INIT_NEED_REQUEST + INIT_NEED_CHECK_OFFLINE);

    if(node_ptr == NULL)
    {
        error_log("ptr is null\n");
        res += INIT_ERR_NODE_NULL;
        return res;
    }
  
    /**> 1、转换类型*/
    circuit_node_t  *temp_node = (circuit_node_t*)node_ptr;             /**> 节点指针 */
    cfg_node_info_t *cfg_info = (cfg_node_info_t*)config_data_ptr;      /**> 配置信息 */


    if(cfg_info->node_type != TYPE_MOD_RELAY)
    {
        error_log("node type:%#X is error ,should %#X \n", cfg_info->node_type,TYPE_MOD_RELAY);
        res += INIT_ERR_TYPE;
        return res;
    }

    /**> 2、 为节点的独有状态和 配置信息创建空间 */ 
    temp_node->node_rt_data     = calloc(1, sizeof(RT_DATA_TYPE(TYPE_MOD_RELAY)));
    temp_node->node_config_data = calloc(1, sizeof(CONFIG_INFO_TYPE(TYPE_MOD_RELAY)));

    /**> 3、初始化 独有实时状态 */
    {
        // 3.1、强转，获得节点的独有状态指针
        RT_DATA_TYPE(TYPE_MOD_RELAY) *rt_data_ptr = \
                        (RT_DATA_TYPE(TYPE_MOD_RELAY) *)temp_node->node_rt_data;

        rt_data_ptr->dev_status = 0;
    }

    //debug_log("relay config is start \n");

    /**> 4、存储 配置信息 */
    {
        /**> ！！！ 配置信息指针 转换类型，必须在config_data 分配空间之后才能进行 ！！！*/
        CONFIG_INFO_TYPE(TYPE_MOD_RELAY) *temp_cfg_para =\
                        (CONFIG_INFO_TYPE(TYPE_MOD_RELAY)*) temp_node->node_config_data;

        /**> 4.1 填充地址 */
        temp_node->node_addr.circuit_ID = cfg_info->dev_addr.circuit_ID;
        temp_node->node_addr.circuit_node_index = cfg_info->dev_addr.circuit_node_index;
      
        /**> 4.2 填充 设备描述 ,这里需要使用strdup 函数，
         *      自动分配一块空间用于存字符串.
         *    ！！！不可以直接赋值 ！！！
         * */
        temp_node->dev_description = strdup(cfg_info->dev_description);
        /**> 4.3 填充 设备类型 */
        temp_node->node_type = cfg_info->node_type;

       /**> 4.4 填充 配置信息 */
        // 填充 下接设备的配置文件名
        temp_cfg_para->config_file_name = strdup(cfg_info->config_para[PARA_1]);
        // 填充 UC编码
        temp_cfg_para->UC_code = strdup(cfg_info->config_para[PARA_2]);
    }
    return  res;
}


/**
 * @brief  IO操作
 * @param node_ptr 端点指针
 * @param ucCommand 控制命令
 * @param argPtr 参数
 * @return int32_t 返回0表示成功，返回1表示失败
 * @attention
 */
static int32_t OP_FUNC_IO_CTR(TYPE_MOD_RELAY)(void *node_ptr, operate_code_t Command, void *argPtr)
{
    int32_t ret = OP_FAIL_PTR_NULL;
    circuit_node_t *temp_node;

    if(node_ptr == NULL) return ret;

    temp_node = (circuit_node_t*)node_ptr;

    switch (Command)
    {
        case OP_CODE_FIND_NODE:
        ret = find_node(temp_node, argPtr);
        break;

    default:
        ret = OP_NOT_SUPPORT;
    break;
    }


    return ret;
}

/**
 * @brief 定时请求
 * @param vPtr 端点指针
 */
static void OP_FUNC_TIMING_REQUEST(TYPE_MOD_RELAY)(void *node_ptr)
{
    return;
}




/**
 * @brief 中继协议解析
 * @param node_ptr 端点
 * @param eProtKind 协议类型
 * @param vDatPtr 数据
 * @param usLen 数据长度
 * @return int32_t 返回-1表示不支持协议类型，返回1表示无法解析，返回0表示成功
 */
static int32_t OP_FUNC_PROTPARSE(TYPE_MOD_RELAY) (void *node_ptr, really_circuit_kind_t eProtKind,
                                                        void *vDatPtr, uint16_t usLen)
{
  
}




/**
 * @brief 设备接口
 */
 node_operate_irf_t OP_FUNC_IRF(TYPE_MOD_RELAY) = {
    .irfInit        = OP_FUNC_INIT(TYPE_MOD_RELAY),
    .irfReset       = OP_FUNC_RESET(TYPE_MOD_RELAY) ,
    .irfIoCtrl      = OP_FUNC_IO_CTR(TYPE_MOD_RELAY),   
    .irfRequest     = OP_FUNC_TIMING_REQUEST(TYPE_MOD_RELAY),  
    .irfProtParse   = OP_FUNC_PROTPARSE(TYPE_MOD_RELAY),
};



/**
 * @brief 根据传入的节点，找到指定地址的下一个节点并返回
 * 
 * @param node_ptr 
 * @param argPtr 
 * @return int 
 */
static int32_t find_node(circuit_node_t *node_ptr, void *argPtr)
{
    if (node_ptr == NULL || argPtr == NULL)
    {
        error_log("node ptr is null or argptr is null ");
        return OP_FAIL_PTR_NULL;
    }
    
    muti_addr_t *addr    = (muti_addr_t *)argPtr;
    uint32_t node_index  = addr->addr_arry_ptr->circuit_node_index;       /*  回路节点索引号 */ 

    /**> 清空 这个存储 目标节点的指针，如果在本设备回路找到，赋新值。如果没找到则返回NULL，认为查找失败 */
    addr->node_ptr = NULL;

    CONFIG_INFO_TYPE(TYPE_MOD_RELAY) *config_data;
    config_data          = (CONFIG_INFO_TYPE(TYPE_MOD_RELAY)*)node_ptr->node_config_data;

    /**> 检查需要查找的节点中间地址是否是按照索引连续排列的，不是就对这个回路进行遍历 */
    if(node_index < config_data->node_tree_ptr.branch_node_number)
    {
        addr->node_ptr = &config_data->node_tree_ptr.branch_ptr[node_index];
    }
    else
    {
       // 遍历 该回路的节点，查找是否存在索引与 目标索引相等的
        for(int i = 0; i < config_data->node_tree_ptr.branch_node_number; i ++)
        {
            if (config_data->node_tree_ptr.branch_ptr[i].node_addr.circuit_node_index\
                 ==  node_index)
            {
                addr->node_ptr = &config_data->node_tree_ptr.branch_ptr[i];             
                break;
            }
        }
    }
    
    addr->addr_num -= 1;            /** 地址级数剥离1位 */
    addr->addr_arry_ptr += 1 ;      /** 地址指针向后偏移1位 */
    return OP_SUCCESS;
}






























